package com.beta.cms.common.until.excel;

import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFColor;

/**
 * @Description Excel工具类
 * @Date 2017年5月23日 下午5:01:16
 * @author xie
 * @version 1.0.0
 */
public class ExcelXlsxUtils {
	/**
	 * 包装Response流
	 * 
	 * @param response
	 * @param fileName
	 * @return
	 * @throws IOException
	 */
	private static OutputStream setResponse(HttpServletResponse response, String fileName) throws IOException {
		response.reset();
		OutputStream out = response.getOutputStream();
		response.setContentType("text/html;charset=utf-8");
		fileName = URLEncoder.encode(fileName, "utf-8");
		response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
		response.setContentType("application/msexcel");
		return out;
	}

	/**
	 * 设置标题属性
	 * 
	 * @param workBook
	 * @return
	 */
	private static XSSFCellStyle setTitleStyle(Workbook workBook) {
		XSSFCellStyle titleStyle = (XSSFCellStyle) workBook.createCellStyle();
		titleStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
		titleStyle.setFillForegroundColor(new XSSFColor(new java.awt.Color(159, 213, 183)));
		titleStyle.setAlignment(CellStyle.ALIGN_CENTER);

		Font font = workBook.createFont();
		font.setColor(HSSFColor.BROWN.index);
		font.setBoldweight(Font.BOLDWEIGHT_BOLD);
		titleStyle.setFont(font);
		return titleStyle;
	}

	/**
	 * 获取所有的成员变量,包括父类
	 * 
	 * @param clazz
	 * @return
	 * @throws Exception
	 */
	public static <T> Field[] getClassFieldsAndSuperClassFields(Class<T> clazz) throws Exception {
		Field[] fields = clazz.getDeclaredFields();
		if (clazz.getSuperclass() == null) {
			throw new Exception(clazz.getName() + "没有父类");
		}
		Field[] superFields = clazz.getSuperclass().getDeclaredFields();
		Field[] allFields = new Field[fields.length + superFields.length];
		for (int i = 0; i < fields.length; i++) {
			allFields[i] = fields[i];
		}
		for (int i = 0; i < superFields.length; i++) {
			allFields[fields.length + i] = superFields[i];
		}
		return allFields;
	}

	/**
	 * 导出excel
	 * 
	 * @param list
	 * @param sh
	 * @param book
	 * @throws Exception
	 */
	public static <T> void getWorkBook(List<T> list, HttpServletResponse response, String fileName) throws Exception {
		SXSSFWorkbook book = new SXSSFWorkbook(5000);
		Sheet sh = book.createSheet();
		OutputStream out = setResponse(response, fileName);
		Field[] fields = getClassFieldsAndSuperClassFields(list.get(0).getClass());
		Excel excel = null;
		Cell cell = null;
		Row row = null;
		int columnIndex = 0;
		int rowColumn = 1;
		if (sh.getLastRowNum() == 0) {
			row = sh.createRow(0);
			XSSFCellStyle titleStyle = setTitleStyle(book);
			for (Field field : fields) {
				field.setAccessible(true);
				excel = field.getAnnotation(Excel.class);
				if (excel == null || excel.skip() == true) {
					continue;
				}
				sh.setColumnWidth(columnIndex, excel.width() * 256);
				cell = row.createCell(columnIndex);
				cell.setCellStyle(titleStyle);
				cell.setCellValue(excel.value());
				columnIndex++;
			}
		}

		CellStyle cs = book.createCellStyle();
		CreationHelper createHelper = book.getCreationHelper();
		for (T t : list) {
			row = sh.createRow(rowColumn);
			columnIndex = 0;
			Object o;
			for (Field field : fields) {
				field.setAccessible(true);
				excel = field.getAnnotation(Excel.class);
				if (excel == null || excel.skip() == true) {
					continue;
				}
				cell = row.createCell(columnIndex);
				o = field.get(t);
				// 常用类型置前
				if (o == null) {
					cell.setCellValue("");
				} else if (o instanceof String) {
					cell.setCellValue((String) o);
				} else if (o instanceof Integer) {
					Integer intValue = (Integer) o;
					cell.setCellValue(intValue);
				} else if (o instanceof Date) {
					cs.setDataFormat(createHelper.createDataFormat().getFormat("yyyy-MM-dd HH:mm:ss"));
					cell.setCellStyle(cs);
					cell.setCellValue((Date) o);
				} else if (o instanceof Double || o instanceof Float) {
					cell.setCellValue((Double) o);
				} else if (o instanceof Long) {
					Long longValue = (Long) o;
					cell.setCellValue(longValue);
				} else {
					cell.setCellValue(o.toString());
				}
				columnIndex++;
			}
			rowColumn++;
		}
		book.write(out);
		book.dispose();
		book.close();
		out.flush();
		out.close();
	}
}
